//
// Created by Ivor_ on 2023/3/4.
//

#ifndef PHYSICAL_COMPUTING_PACKAGE_ORDINARYDIFFERENTIALEQUATION_H
#define PHYSICAL_COMPUTING_PACKAGE_ORDINARYDIFFERENTIALEQUATION_H

#include <malloc.h>
#include <math.h>

/**
 * @author Ivor
 * @param numOfPoints how many points do you have, the initial point should be included
 * @param variableVals all points' variable values
 * @param functionValueInit the function value of the first variable, for the solve progress start
 * @param accuracy implicit iteration method only, to control iteration steps
 * @param derivativeFunction just as its name, need a function pointer with arguments variable value "x" and function value "y" and return its derivative function value
 * @return the function value one-to-one corresponding to variableVals
 * @remark step size is not limited, any condition could be solve, it just shows in your argument variableVals, even negative can be accepted, however, you should check it whether convergence or not in advance
 */
double* eulerExplicitOde(int numOfPoints, double* variableVals, double functionValueInit, double(*derivativeFunction)());
double* eulerImplicitIterationOde(int numOfPoints, double* variableVals, double functionValueInit, double accuracy, double(*derivativeFunction)());
double* eulerImplicitForecastCorrectOde(int numOfPoints, double* variableVals, double functionValueInit, double(*derivativeFunction)());
double* rungeKutta2Ode(int numOfPoints, double* variableVals, double functionValueInit, double(*derivativeFunction)());
double* rungeKutta3Ode(int numOfPoints, double* variableVals, double functionValueInit, double(*derivativeFunction)());
double* rungeKutta4Ode(int numOfPoints, double* variableVals, double functionValueInit, double(*derivativeFunction)());

/**
 * @author Ivor
 * @param numOfPoints how many points do you have, the initial point should be included
 * @param variableVals all points' variable values
 * @param functionValuesInit the function values of the first few variables, for the solve progress start, the number of variables must be equal to the order number
 * @param derivativeFunction just as its name, need a function pointer with arguments variable value "x" and function value "y" and return its derivative function value
 * @return the function value one-to-one corresponding to variableVals
 * @remark step size is not strictly limited, at least they are well-distributed, for example, (x[i+1] - x[i]) must be a constant with any possible i, negative constant can be accepted, however, you should check it whether convergence or not in advance
 */
double* adamsExplict2Ode(int numOfPoints, double* variableVals, double* functionValuesInit, double(*derivativeFunction)());
double* adamsExplict3Ode(int numOfPoints, double* variableVals, double* functionValuesInit, double(*derivativeFunction)());
double* adamsExplict4Ode(int numOfPoints, double* variableVals, double* functionValuesInit, double(*derivativeFunction)());

#endif //PHYSICAL_COMPUTING_PACKAGE_ORDINARYDIFFERENTIALEQUATION_H
